﻿using System;
using System.ComponentModel.Design;
using Microsoft.VisualStudio.Shell;
using VsxTools.Attributes;

namespace VsxTools.MenuCommandService
{
    public abstract class MenuCommandHandler
    {
        private readonly Package _package;
        private readonly CommandID _commandId;
        private OleMenuCommand _menuCommand;

        protected internal MenuCommandHandler(Package package)
        {
            _package = package;
            foreach (var attribute in GetType().GetCustomAttributes(false))
            {
                var idAttribute = attribute as CommandIdAttribute;
                if (idAttribute != null)
                {
                    _commandId = new CommandID(idAttribute.Guid, (int)idAttribute.Command);
                }
            }
        }

        public CommandID CommandId
        {
            get { return _commandId; }
        }

        protected Package Package
        {
            get { return _package; }
        }

        protected IServiceProvider ServiceProvider
        {
            get { return _package; }
        }

        protected OleMenuCommand MenuCommand
        {
            get { return _menuCommand; }
        }

        public bool IsBound
        {
            get { return _menuCommand != null; }
        }

        protected virtual void OnExecute(OleMenuCommand command)
        {
            
        }

        protected virtual void OnQueryStatus(OleMenuCommand command)
        {
            
        }

        protected virtual void OnChange(OleMenuCommand command)
        {
            
        }

        public void Bind()
        {
            if (_package != null) return;
            var mcs =
                ServiceProvider.GetService(typeof (IMenuCommandService)) as OleMenuCommandService;
            if (mcs == null) return;

            _menuCommand = new OleMenuCommand(ExecuteMenuCommandCallback, ChangeCallback, BeforeStatusQueryCallback,
                _commandId);
            mcs.AddCommand(_menuCommand);
        }

        private void ExecuteMenuCommandCallback(object sender, EventArgs e)
        {
            var command = sender as OleMenuCommand;
            if (command != null) OnExecute(command);
        }

        private void ChangeCallback(object sender, EventArgs e)
        {
            var command = sender as OleMenuCommand;
            if (command != null) OnChange(command);
        }

        private void BeforeStatusQueryCallback(object sender, EventArgs e)
        {
            var command = sender as OleMenuCommand;
            if (command != null) OnQueryStatus(command);
        }
    }
}
